﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using IceDog.DNC.Web.Swashbuckle1_X.Convention;
using IceDog.DNC.Web.Swashbuckle1_X.CustomAttribute;
using IceDog.DNC.Web.Swashbuckle1_X.Filter;
using IceDog.DNC.Web.Swashbuckle1_X.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Newtonsoft.Json.Serialization;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace IceDog.DNC.Web.Swashbuckle1_X
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddMvc();
            services.AddMvc(o =>
                {
                    o.Filters.Add<AuthFilter>();
                    o.Conventions.Add(new ApiExplorerGroupPerVersionConvention());//添加自定义的版本区分约定
                    //o.Conventions.Add(new ApiExplorerGetsOnlyConvention());//仅显示Get请求
                })
                .AddJsonOptions(o =>
                {
                    o.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;//格式化返回的json
                    o.SerializerSettings.DateFormatString = "YYYY/MM/DD hh:mm:ss";//格式化返回的日期
                    //o.SerializerSettings.ContractResolver =new CamelCasePropertyNamesContractResolver();
                });
            //services.AddMvcCore().AddApiExplorer();//如果是使用AddMvcCore，需要显示添加ApiExplorer
            //添加swagger生成器
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "Nano API",
                    Description = "A Simple Example ASP.NET Core Web API",
                    TermsOfService = "None",
                    Contact = new Contact
                    {
                        Name = "DHclly",
                        Email = "335121817@qq.com",
                        Url = "https://www.example.com/DHclly"
                    },
                    License = new License
                    {
                        Name = "Use under LICX",
                        Url = "https://example.com/license"
                    }
                });
                c.SwaggerDoc("v2", new Info()
                {
                    Version = "v2",
                    Title = "Nano API",
                    Description = "A Simple Example ASP.NET Core Web API",
                    TermsOfService = "None",
                    Contact = new Contact
                    {
                        Name = "DHclly",
                        Email = "335121817@qq.com",
                        Url = "https://www.example.com/DHclly"
                    },
                    License = new License
                    {
                        Name = "Use under LICX",
                        Url = "https://example.com/license"
                    }
                });
                //通过自定义特性ApiVersion来控制api接口在特定的版本,true显示，false，不显示
                c.DocInclusionPredicate((docName, apiDesc) =>
                {
                    var versions = apiDesc.ControllerAttributes()
                        .OfType<ApiVersionAttribute>()
                        .SelectMany(attr => attr.Versions);
                    var enumerable = versions as IList<string> ?? versions.ToList();
                    if (enumerable.Count == 0)
                    {
                        return true;
                    }
                    var result = enumerable.Any(v => $"v{v.ToString()}" == docName);
                    return result;
                });

                //过滤含有Obsolete特性的方法
                //c.IgnoreObsoleteActions();
                //c.IgnoreObsoleteProperties();

                //c.TagActionsBy(api=>api.HttpMethod);//通过请求行为分组
                //c.OrderActionsBy((apiDesc) =>
                //{
                //    //var sort = $"{apiDesc.ActionDescriptor.RouteValues["controller"]}_{apiDesc.HttpMethod}";
                //    var sort = $"{apiDesc.ActionDescriptor.RouteValues["controller"]}_{apiDesc.ActionDescriptor.RouteValues["action"]}";
                //    Console.WriteLine(sort);
                //    return sort;
                //});
                //c.CustomSchemaIds((type) => type.FullName);//给返回的同名模型的完全限定名为id,如区分 a.product和b.product,只用product是无法区分的

                c.DescribeAllEnumsAsStrings();//描述枚举值为字面量，而不是数值
                c.DescribeStringEnumsInCamelCase();//所有枚举变量用camelCase
                c.DescribeAllParametersInCamelCase();//所有参数变量用camelCase


                //c.MapType<PhoneNumber>(()=>new Schema(){Type = "string"});//用于自定义转换

                c.OperationFilter<AuthResponsesOperationFilter>();
                c.SchemaFilter<AutoRestSchemaFilter>();
                c.DocumentFilter<TagDescriptionsDocumentFilter>();

                // Define the OAuth2.0 scheme that's in use (i.e. Implicit Flow)
                c.AddSecurityDefinition("oauth2", new OAuth2Scheme
                {
                    Type = "oauth2",
                    Flow = "implicit",
                    AuthorizationUrl = "http://petstore.swagger.io/oauth/dialog",
                    Scopes = new Dictionary<string, string>
                    {
                        { "readAccess", "Access read operations" },
                        { "writeAccess", "Access write operations" }
                    }
                });

                //2.x才有
                //c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
                //{
                //    { "oauth2", new[] { "readAccess", "writeAccess" } }
                //});

                //给swagger生成器设置项目生成的xml注释文档的路径
                var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
                //var basePath = AppContext.BaseDirectory;
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                var xmlPath = Path.Combine(basePath, xmlFile);
                c.IncludeXmlComments(xmlPath);//可以调用多个
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler();
            }


            app.Use(async (ctx,next)=>
            {
                if (ctx.Request.Method=="GET"&&ctx.Request.Path.Value.IndexOf("doc", StringComparison.Ordinal) >-1 && !(ctx.Request.QueryString.Value.IndexOf("s11", StringComparison.Ordinal) > -1))
                {
                    ctx.Response.Redirect("/api/values");
                    return;
                }
                await next.Invoke(); ;
            });

            app.UseMvc();
            app.UseStaticFiles();

            //使中间件可以提供生成swagger.json文件
            //app.UseSwagger();//默认路由位置 "swagger/{documentName}/swagger.json"
            app.UseSwagger(c =>
            {
                c.RouteTemplate = "api-docs/{documentName}/swagger.json";//自定义路由模板
                c.PreSerializeFilters.Add((doc, req) =>
                {
                    doc.Host = req.Host.Value;
                    //doc.BasePath = req.Host.Value;
                    //doc.Tags = new List<Tag>() { new Tag() { Name = "Nano" } };
                });
            });

            // 使中间件可以通过给定的提供swagger.json文件来填充swagger UI 界面
            app.UseSwaggerUI(c =>
            {
                //UI右上侧的下拉列表
                //c.SwaggerEndpoint("/swagger/v1/swagger.json", "Nano V1");
                //c.SwaggerEndpoint("/swagger/v2/swagger.json", "Nano V2");
                c.SwaggerEndpoint("/api-docs/v1/swagger.json", "Nano V1");
                c.SwaggerEndpoint("/api-docs/v2/swagger.json", "Nano V2");

                c.RoutePrefix = "doc";//修改访问ui的路由，默认swagger
                c.DocumentTitle("Nano Api Explorer");

                //新版本不能这么干了,必须自己加
                c.InjectOnCompleteJavaScript("/swagger/translator/zh-cn.js");//注入翻译js
                //c.InjectStylesheet("/swagger/translator/zh-cn.js");
                //c.InjectOnFailureJavaScript("/swagger-ui/custom.css");
                //c.IndexStream = () => GetType().GetTypeInfo().Assembly
                //  .GetManifestResourceStream("CustomUIIndex.Swagger.index.html"); // requires file to be added as an embedded resource

                
            });
        }
    }
}
